/*-------------------------------------------------------------------------------------------------*/
/* File Name:                                                                                      */
/*     httpd.c                                                                                     */
/* Description:                                                                                    */
/*     This application is a ultra simple httpd base on lwIP                                       */
/*     A JPG file should be write to 0xA0020000 in advance, and the size should be known           */
/*     This file is modified from a sample code in original lwIP package                           */
/* History:                                                                                        */
/*                                                                                                 */
/* Project:                                                                                        */
/*-------------------------------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "wblib.h"
#include "NUC900_lwip.h"


//#define USE_DHCP

/* webpage.*/
CHAR *jpg;   /* A jpeg locates in 0xa0020000, size 3446383 bytes */
static CHAR webpage_[] =
    "HTTP/1.0 200 OK\r\nContent-length: 3446383\r\nContent-type: image/jpeg\r\n\r\n";
#define _SIZE   1200  // TCP segment size
INT _flag = 0;
struct tcp_pcb *_pcb;



/* recv callback function */
static err_t _HttpRecv(void *arg, struct tcp_pcb *pcb, struct pbuf*p, err_t err)
{
    CHAR *rq;
    /* If we got a NULL pbuf in p, the remote end has closed
    the connection.*/
    if (p != NULL)
    {

        /* The payload pointer in the pbuf contains the data
        in the TCP segment.*/

        rq = p->payload;
        /* Check if the request was an HTTP "GET /\r\n". */
        if (rq[0]=='G' && rq[1] == 'E' &&
                rq[2] == 'T' && rq[3] == ' '&&
                rq[4] == '/' ) {

            /* Send the webpage to the remote host. A zero
            in the last argument means that the data should
            no tbe copied into internal buffers. */

            if (_flag == 0) { // we only service one connection at a time.
                tcp_recved(pcb, p->tot_len);
                // Send header here, main() will send the body
                tcp_write(pcb, webpage_, sizeof(webpage_) -1, 0);
                _flag = 1;
                _pcb = pcb;
            }else
                tcp_close(pcb);
        }
        /* Free the pbuf. */
        pbuf_free(p);
    }

    return(ERR_OK);
}

/*accept callback function */
static err_t _HttpAccept(void *arg,struct tcp_pcb *pcb, err_t err)
{
    /* Setup the function http_recv() to be called when data
    arrives.*/
    tcp_recv(pcb, _HttpRecv);
    return ERR_OK;
}

/*httpd initialization function.*/
static void _HttpdInit(void)
{
    struct tcp_pcb *pcb, *pcb_listen;
    /*Create a new TCP PCB.*/
    pcb = tcp_new();
    /*Bind the PCB to TCP port 80.*/
    if (tcp_bind(pcb,NULL,80) != ERR_OK)
        sysprintf("bind error\n");
    /*Change TCP state to LISTEN.*/
    pcb_listen = tcp_listen(pcb);
    /*Setup http_accet() function to be called
    when a new connection arrives.*/
    tcp_accept(pcb_listen, _HttpAccept);
}


struct ip_addr gw, ipaddr, netmask;
struct netif netif;
/* network initialization function.*/
static VOID _NetInit(VOID)
{



#ifdef USE_DHCP

    IP4_ADDR(&gw, 0, 0, 0, 0);
    IP4_ADDR(&ipaddr, 0, 0, 0, 0);
    IP4_ADDR(&netmask, 0, 0, 0, 0);

#else

    IP4_ADDR(&gw, 192, 168, 0, 1);
    IP4_ADDR(&ipaddr, 192, 168, 0, 227);
    IP4_ADDR(&netmask, 255, 255, 255, 0);

#endif

    stats_init();
    sys_init();

    /*   mem_init(); */
    memp_init();
    pbuf_init();



    etharp_init();

    ip_init();
    udp_init();
    tcp_init();


#ifdef USE_DHCP
    netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ip_input);
    netif_set_default(&netif);
    dhcp_start(&netif);
#else

    netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ip_input);
    netif_set_default(&netif);
    netif_set_up(&netif);
#endif
}

static VOID _InitSystem(VOID)
{

    WB_PLL_T sysClock;

    sysDisableCache();
    sysInvalidCache();
    sysSetMMUMappingMethod(MMU_DIRECT_MAPPING);
    sysEnableCache(CACHE_WRITE_BACK);

    sysClock.pll0 = PLL_166MHZ;
    sysClock.pll1 = PLL_100MHZ;
    sysClock.cpu_src = CPU_FROM_PLL0;
    sysClock.ahb_clk = AHB_CPUCLK_1_2;
    sysClock.apb_clk = APB_AHB_1_2;

    sysSetPLLConfig(&sysClock);

}

int main(void)
{

    INT i, j;
    INT _err;

    _InitSystem();

    _NetInit();
    _HttpdInit();

    while (1) {
        if (_flag == 1) {
            jpg = (char *)0xa0020000;
            i = 0;
            while (1) {
                if (i == 3446383)
                    break;
                if (i + _SIZE > 3446383)
                    j = 3446383 - i;
                else
                    j = _SIZE;

                _err = tcp_write(_pcb, jpg + i, j, 0);

                if (_err == ERR_MEM) {
                    continue;
                } else if (_err == ERR_OK) {
                    i += j;
                    /* sysprintf("%d bytes sent\n", i); */
                } else {
                    /* sysprintf("error number: %d\n", _err); */
                    break;
                }
            }
            _flag = 0;
            tcp_close(_pcb);
        }
    }
}






